home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_12_02 / smith / dbaz.c < prev    next >
C/C++ Source or Header  |  1993-12-29  |  5KB  |  165 lines

  1. /* DBAZ.C
  2.  * Contributed to Public Domain 9/93
  3.  * by Thad Smith, Boulder Co.
  4.  */
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include "baz.h"
  8. #include "bazcom.h"
  9. #include "crc16.h"
  10.  
  11. #define LAST_CODE   (FIRST_CODE + BASE -1)
  12. #define BASESQ      (unsigned long)(BASE*BASE)
  13. #define BASEVAL(c)  (unsigned)((c)-FIRST_CODE)
  14. #define ISENCODE(c) ((c) >= FIRST_CODE && \
  15.                      (c) <= LAST_CODE)
  16.  
  17. static unsigned int crc;/* input file CRC */
  18. static size_t n_unused; /* # unused input bytes  */
  19. static int  ninb;       /* # bytes in inbuf      */
  20. static int  done;       /* set if finished       */
  21. static char inbuf[ENCB_LEN * 2 + 2];
  22. static unsigned char outbuf[BINB_LEN * 2];
  23. static int  (*outfunc) (const char *out, size_t len);
  24.  
  25. static decode_stat
  26. decode_endmark(const char *data, size_t len);
  27.  
  28. /* Initialize the BAZ911 decoder. */
  29. int dbaz_init (outf_t *p_outfunc) {
  30.    initcrctab ();
  31.    crc = CRC_INIT_VALUE;
  32.    done = 0;
  33.    ninb = 0;
  34.    n_unused = 0;
  35.    outfunc = p_outfunc;
  36.    return 0;
  37. }
  38.  
  39. /* Decode block of data. */
  40. decode_stat
  41. dbaz_data (const unsigned char *data, size_t len) {
  42.    int         s;       /* output return status */
  43.  
  44.    if (done) {
  45.       n_unused += len;
  46.       return DECR_END;
  47.    } else if (len == 0)
  48.       return DECR_NO_ENDMARK;
  49.  
  50.    for (;;) {
  51.       /* fill block input buffer */
  52.       while (ninb < ENCB_LEN) {
  53.          if (ISENCODE(*data))
  54.             inbuf[ninb++] = (char) *data;
  55.          data++;
  56.          if (--len == 0)
  57.             return DECR_OK;
  58.  
  59.       }
  60.       if (*inbuf == END_FLAG) {
  61.          return decode_endmark ((const char *) data,
  62.                                               len );
  63.       }
  64.       if (decode_11_to_9 (outbuf, inbuf))
  65.          return DECR_INVALID_DATA;
  66.       ninb = 0;
  67.       crc = updcrc (crc, outbuf, BINB_LEN);
  68.       if ((s= outfunc ((char *)outbuf,BINB_LEN)) != 0)
  69.          return (decode_stat) s;
  70.    }
  71. }
  72.  
  73. /* Return number of characters in internal buffer.
  74.  * This can be used after DECR_END status is returned
  75.  * to determine the number of unused characters given
  76.  * to the decoder.                                  */
  77. size_t dbaz_excess_chars (void) {
  78.    return n_unused;
  79. }
  80.  
  81. decode_stat decode_endmark (
  82.    const char *data,    /* data following inbuf     */
  83.    size_t len           /* length of data           */
  84. )
  85. {
  86.    int         s;       /* output return status     */
  87.    int         nreq;    /* # input bytes required for
  88.                          * end ensemble             */
  89.    unsigned int rc;     /* # remaining data bytes   */
  90.  
  91.    if ((rc = BASEVAL(inbuf[1])) > MAX_ENDBLK_DB)
  92.       return DECR_INVALID_DATA;
  93.  
  94.    memset (inbuf+ninb, FIRST_CODE, 2*ENCB_LEN+2-ninb);
  95.    nreq = rc +4 +CRCLBY;
  96.    if (nreq < ENCB_LEN)
  97.       nreq = ENCB_LEN;      /* min size is 1 block */
  98.    if (rc > BINB_LEN - CRCLBY)
  99.       nreq += 2;            /* use part of 2nd blk */
  100.    /* get remaining characters */
  101.    while (ninb < nreq) {
  102.       if (len == 0)
  103.          return DECR_OK;    /* need more input chars */
  104.       if (ISENCODE(*data))
  105.          inbuf[ninb++] = *data;
  106.       data++;
  107.       len--;
  108.    }
  109.    done = 1;
  110.    if (decode_11_to_9 (outbuf, inbuf+2))
  111.       return DECR_INVALID_DATA;
  112.    if (rc > BINB_LEN - CRCLBY) {
  113.       if (decode_11_to_9 (outbuf+BINB_LEN,
  114.                           inbuf+2+ENCB_LEN))
  115.          return DECR_INVALID_DATA;
  116.    }
  117.    crc = updcrc (crc, outbuf, rc);
  118.    if ((s = outfunc ((char *) outbuf, rc)) != 0)
  119.  
  120.        return (decode_stat) s;
  121.    if (((crc >> 8) & 0xff) != outbuf[rc] ||
  122.        ( crc       & 0xff) != outbuf[rc+1] )
  123.       return DECR_CRC_ERR;
  124.    n_unused = len;
  125.    return DECR_END;
  126. }
  127.  
  128. /* Decode 11 printable ASCII characters into 9 bytes */
  129. int             /* return: 0=OK, 1= invalid input */
  130. decode_11_to_9 (unsigned char out[], const char in[]) {
  131.    unsigned long block;
  132.    unsigned    b2, q1, q2, i;
  133.  
  134.    block = BASEVAL(in[0]) * BASESQ +
  135.       (BASEVAL(in[1]) * BASE + BASEVAL(in[2]));
  136.    out[0] = (unsigned) block & 0xff;
  137.    b2 = (unsigned) (block >> 8);
  138.    q1 = b2 / PBASE;
  139.    q2 = b2 - q1 * PBASE;
  140.    if (q1 >= PBASE) return 1;
  141.  
  142.    for (i = 1; i < 9; i += 4) {
  143.       block = (BASEVAL(in[i+2]) * BASE +
  144.                BASEVAL(in[i+3])) * BASESQ +
  145.          (BASEVAL(in[i+4]) * BASE + BASEVAL(in[i+5]));
  146.  
  147.       if (((unsigned)(block >> 16) >= PBMULT) ||
  148.           q1 == PBASE-1 && block >
  149.           (0xffffffffUL -(PBMULT*(PBASE-1UL) << 16))) {
  150.          return 1;
  151.       }
  152.  
  153.       block += (unsigned long) (q1 * PBMULT) << 16;
  154.       out[i+0] = (unsigned char) (block >> 24);
  155.       out[i+1] = (unsigned char) (block >> 16);
  156.       out[i+2] = (unsigned char) (block >> 8);
  157.       out[i+3] = (unsigned char) block;
  158.       q1 = q2;
  159.    }
  160.    return 0;
  161. }
  162.  
  163. /* End of File */ 
  164.  
  165.